<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Dashboard - RINT 数据分享平台</title>
    <link href="/static/bootstrap/bootstrap.min.css" rel="stylesheet">
    <link href="/static/style.css" rel="stylesheet">
    <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">RINT 数据分享平台</a>
            <div class="navbar-nav ms-auto" id="navbarNav">
                <!-- Navigation will be updated by JavaScript based on authentication state -->
            </div>
        </div>
    </nav>

    <div class="container mt-4">
        <div class="row">
            <div class="col-md-12">
                <div class="d-flex justify-content-between align-items-center mb-4">
                    <h2 id="pageTitle">数据仓库</h2>
                    <div class="d-flex align-items-center" id="userControls">
                        <!-- User controls will be updated by JavaScript based on authentication state -->
                    </div>
                </div>
                
                <!-- Login message will be inserted here by JavaScript -->
                <div id="loginMessageContainer"></div>
            </div>
        </div>
    </div>

    <!-- Data items moved to the end of the page -->
    <div class="container mt-4">
        <div class="row">
            <div class="col-md-12">
                <div id="dataItemsList" class="row">
                    <!-- Data items will be loaded here -->
                </div>
            </div>
        </div>
    </div>

    <!-- Upload Modal -->
    <div class="modal fade" id="uploadModal" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Upload Data</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body">
                    <form id="uploadForm">
                        <div class="mb-3">
                            <label class="form-label">上传类型</label>
                            <div class="form-check">
                                <input class="form-check-input" type="radio" name="uploadType" id="fileUpload" value="file" checked>
                                <label class="form-check-label" for="fileUpload">文件</label>
                            </div>
                            <div class="form-check">
                                <input class="form-check-input" type="radio" name="uploadType" id="folderUpload" value="folder">
                                <label class="form-check-label" for="folderUpload">文件夹</label>
                            </div>
                        </div>
                        <div class="mb-3">
                            <label for="uploadFile" class="form-label">选择文件/文件夹</label>
                            <input type="file" class="form-control" id="uploadFile" required multiple placeholder="选择要上传的文件或文件夹">
                            <div class="form-text" id="uploadHelpText">支持选择多个文件，或选择文件夹上传其中所有文件。</div>
                        </div>
                        
                        <div class="mb-3">
                            <label for="itemProject" class="form-label">所属项目</label>
                            <input type="text" class="form-control" id="itemProject" placeholder="源码项目名称和 Gitlab 项目地址，例如：MAF-Embedding, https://gitlab.hillstonenet.com/rintbj/MAF-Embedding/">
                        </div>
                        
                        <div class="mb-3">
                            <label for="itemSource" class="form-label">数据来源</label>
                            <input type="text" class="form-control" id="itemSource" required placeholder="原始数据下载链接，例如：https://github.com/verazuo/jailbreak_llms/blob/main/data/forbidden_question/forbidden_question_set_with_prompts.csv.zip">
                        </div>
                        <div class="mb-3">
                            <label for="itemDescription" class="form-label">详细说明</label>
                            <textarea class="form-control" id="itemDescription" rows="3" placeholder="例如：此数据集用于角色扮演类提示词注入攻击测试..."></textarea>
                        </div>
                        <div class="mb-3">
                            <label for="parentItem" class="form-label">父级项目 (可选)</label>
                            <select class="form-select" id="parentItem">
                                <option value="">无</option>
                            </select>
                        </div>
                        <div class="mb-3">
                            <div class="form-check">
                                <input class="form-check-input" type="checkbox" id="makePublic">
                                <label class="form-check-label" for="makePublic">
                                    设为公开数据 (⚠️ 公开后无法删除，请谨慎选择)
                                </label>
                            </div>
                        </div>
                        <button type="submit" class="btn btn-primary" id="uploadButton">上传</button>
                    </form>
                    <div id="uploadProgress" class="mt-3" style="display: none;">
                        <div class="progress">
                            <div class="progress-bar" role="progressbar" style="width: 0%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
                        </div>
                        <div class="mt-2">
                            <small id="uploadStatus">准备上传...</small>
                        </div>
                    </div>
                    <div id="uploadMessage" class="mt-3"></div>
                </div>
            </div>
        </div>
    </div>

    <!-- Lineage Modal -->
    <div class="modal fade" id="lineageModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Data Lineage</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body">
                    <div id="lineageContent">
                        <!-- Lineage visualization will be loaded here -->
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- Delete Confirmation Modal -->
    <div class="modal fade" id="deleteConfirmModal" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="deleteConfirmTitle">确认删除</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body" id="deleteConfirmBody">
                    确定要删除这个数据项吗？此操作无法撤销。
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                    <button type="button" class="btn btn-danger" id="confirmDeleteButton">删除</button>
                </div>
            </div>
        </div>
    </div>

    <!-- Download Progress Modal -->
    <div class="modal fade" id="downloadProgressModal" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="false">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">
                        <i class="bi bi-download"></i> 正在下载数据文件
                    </h5>
                </div>
                <div class="modal-body">
                    <div class="mb-3">
                        <div class="d-flex justify-content-between align-items-center mb-2">
                            <span id="downloadFileName">文件名</span>
                            <span id="downloadPercentage">0%</span>
                        </div>
                        <div class="progress">
                            <div class="progress-bar progress-bar-striped progress-bar-animated" 
                                 id="downloadProgressBar" 
                                 role="progressbar" 
                                 style="width: 0%" 
                                 aria-valuenow="0" 
                                 aria-valuemin="0" 
                                 aria-valuemax="100">0%</div>
                        </div>
                    </div>
                    
                    <div class="row text-center">
                        <div class="col-4">
                            <small class="text-muted">已下载</small>
                            <div id="downloadedSize">0 MB</div>
                        </div>
                        <div class="col-4">
                            <small class="text-muted">总大小</small>
                            <div id="totalSize">未知</div>
                        </div>
                        <div class="col-4">
                            <small class="text-muted">下载速度</small>
                            <div id="downloadSpeed">0 MB/s</div>
                        </div>
                    </div>
                    
                    <div class="text-center mt-3">
                        <small class="text-muted">
                            <i class="bi bi-clock"></i> 
                            预计剩余时间: <span id="downloadETA">计算中...</span>
                        </small>
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-danger" id="cancelDownloadButton">
                        <i class="bi bi-x-circle"></i> 取消下载
                    </button>
                </div>
            </div>
        </div>
    </div>

    <script src="/static/bootstrap/bootstrap.bundle.min.js"></script>
    <script>
        // Timing configuration - can be controlled via environment or config
        const TIMING_DEBUG_ENABLED = true; // Set to true to enable frontend timing debugging
        
        // Page load timing
        if (TIMING_DEBUG_ENABLED) {
            console.time('page-load-to-script');
            console.log('TIMING: Script execution started');
        }
        
        let authToken = localStorage.getItem('token');
        let currentUser = null;
        let currentLineageItemId = null;
        
        // Note: Fetch interceptor is now handled within loadCurrentUser() to avoid race conditions
        
        if (TIMING_DEBUG_ENABLED) {
            console.log('TIMING: Variables initialized, authToken exists:', !!authToken);
        }

        async function loadCurrentUser() {
            if (TIMING_DEBUG_ENABLED) {
                console.time('loadCurrentUser');
                console.log('TIMING: loadCurrentUser - starting');
            }

            try {
                // If we have a token, use it directly
                if (authToken) {
                    if (TIMING_DEBUG_ENABLED) {
                        console.time('me-fetch');
                        console.log('TIMING: loadCurrentUser - fetching /api/user-info with token');
                    }
                    const response = await fetch('/api/user-info', {
                        headers: {
                            'Authorization': `Bearer ${authToken}`
                        }
                    });
                    if (TIMING_DEBUG_ENABLED) {
                        console.timeEnd('me-fetch');
                    }

                    if (response.ok) {
                        if (TIMING_DEBUG_ENABLED) {
                            console.time('me-parse');
                        }
                        currentUser = await response.json();
                        updateNavigation();
                        if (TIMING_DEBUG_ENABLED) {
                            console.timeEnd('me-parse');
                            console.log('TIMING: loadCurrentUser - completed via token');
                        }
                    } else {
                        // If token is invalid, clear it and continue as unauthenticated
                        localStorage.removeItem('token');
                        document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax';
                        authToken = null;
                        currentUser = null;
                        updateNavigation();
                        if (TIMING_DEBUG_ENABLED) {
                            console.log('TIMING: loadCurrentUser - failed token authentication');
                        }
                    }
                } else {
                    // No token available, try server-side authentication without triggering interceptor
                    if (TIMING_DEBUG_ENABLED) {
                        console.time('me-server-fetch');
                        console.log('TIMING: loadCurrentUser - fetching /api/user-info without token');
                    }

                    // Use a flag to prevent the interceptor from redirecting during this call
                    const originalFetch = window.fetch;
                    window.fetch = async function(...args) {
                        const response = await originalFetch.apply(this, args);

                        // Only redirect to login if this is not a user-info call and status is 401
                        if (response.status === 401 && !args[0].includes('/api/user-info')) {
                            // Clear invalid token
                            localStorage.removeItem('token');
                            document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax';

                            // Get current path for redirect
                            const currentPath = window.location.pathname + window.location.search;
                            const redirectUrl = `/login?redirect=${encodeURIComponent(currentPath)}`;

                            // Redirect to login
                            window.location.href = redirectUrl;
                            return Promise.reject(new Error('Unauthorized - redirecting to login'));
                        }

                        return response;
                    };

                    try {
                        const serverResponse = await fetch('/api/user-info');
                        if (TIMING_DEBUG_ENABLED) {
                            console.timeEnd('me-server-fetch');
                        }

                        if (serverResponse.ok) {
                            if (TIMING_DEBUG_ENABLED) {
                                console.time('me-server-parse');
                            }
                            currentUser = await serverResponse.json();
                            updateNavigation();
                            if (TIMING_DEBUG_ENABLED) {
                                console.timeEnd('me-server-parse');
                                console.log('TIMING: loadCurrentUser - completed via server-side auth');
                            }
                        } else {
                            currentUser = null;
                            updateNavigation();
                            if (TIMING_DEBUG_ENABLED) {
                                console.log('TIMING: loadCurrentUser - server-side auth failed');
                            }
                        }
                    } finally {
                        // Restore the original interceptor
                        window.fetch = originalFetch;
                    }
                }
            } catch (error) {
                console.error('Error loading current user:', error);
                // If there's an error, continue as unauthenticated
                currentUser = null;
                updateNavigation();
                if (TIMING_DEBUG_ENABLED) {
                    console.log('TIMING: loadCurrentUser - error occurred');
                }
            }

            if (TIMING_DEBUG_ENABLED) {
                console.timeEnd('loadCurrentUser');
            }
        }

        function updateNavigation() {
            const navbarNav = document.getElementById('navbarNav');
            const userControls = document.getElementById('userControls');
            
            if (currentUser) {
                // User is logged in
                navbarNav.innerHTML = `
                    <a class="nav-link" href="/dashboard">数据仓库</a>
                    ${currentUser.is_admin ? '<a class="nav-link" href="/admin">Admin Panel</a>' : ''}
                    <div class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                            <span id="currentUserEmail">${currentUser.email}</span>
                        </a>
                        <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
                            <li><a class="dropdown-item" href="#" onclick="logout()">Logout</a></li>
                        </ul>
                    </div>
                `;
                
                userControls.innerHTML = `
                    <div class="form-check me-3">
                        <input class="form-check-input" type="checkbox" id="myDataCheckbox">
                        <label class="form-check-label" for="myDataCheckbox">
                            只显示我的数据
                        </label>
                    </div>
                    <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#uploadModal">
                        上传数据
                    </button>
                `;
            } else {
                // User is not logged in
                navbarNav.innerHTML = `
                    <a class="nav-link" href="/login">Login</a>
                    <a class="nav-link" href="/register">Register</a>
                `;
                
                userControls.innerHTML = '';
            }
        }

        async function loadDataItems() {
            if (TIMING_DEBUG_ENABLED) {
                console.time('loadDataItems');
            }
            
            try {
                // Determine if we should filter by user
                const userOnly = document.getElementById('myDataCheckbox') && document.getElementById('myDataCheckbox').checked;
                const isAuthenticated = currentUser !== null;
                
                let url;
                if (isAuthenticated) {
                    url = `/api/data?user_only=${userOnly}`;
                } else {
                    url = '/api/data/public';
                }
                
                if (TIMING_DEBUG_ENABLED) {
                    console.log(`TIMING: loadDataItems - fetching ${url}`);
                    console.time('data-fetch');
                }
                const response = await fetch(url, {
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                if (TIMING_DEBUG_ENABLED) {
                    console.timeEnd('data-fetch');
                }
                
                if (response.ok) {
                    if (TIMING_DEBUG_ENABLED) {
                        console.time('data-parse');
                    }
                    
                    const responseData = await response.json();
                    const dataItems = responseData.items || [];
                    if (TIMING_DEBUG_ENABLED) {
                        console.timeEnd('data-parse');
                        console.log(`TIMING: loadDataItems - got ${dataItems.length} items`);
                    }
                    
                    if (TIMING_DEBUG_ENABLED) {
                        console.time('display-data');
                    }
                    displayDataItems(dataItems);
                    updateParentOptions(dataItems);
                    updatePageTitle(userOnly);
                    if (TIMING_DEBUG_ENABLED) {
                        console.timeEnd('display-data');
                    }
                } else {
                    console.error('Failed to load data items');
                    if (TIMING_DEBUG_ENABLED) {
                        console.log('TIMING: loadDataItems - failed with status:', response.status);
                    }
                }
            } catch (error) {
                console.error('Error loading data items:', error);
                if (TIMING_DEBUG_ENABLED) {
                    console.log('TIMING: loadDataItems - error occurred');
                }
            }
            
            if (TIMING_DEBUG_ENABLED) {
                console.timeEnd('loadDataItems');
            }
        }

        function displayDataItems(dataItems) {
            const container = document.getElementById('dataItemsList');
            container.innerHTML = '';
            
            dataItems.forEach(item => {
                const card = document.createElement('div');
                card.className = 'col-md-4 mb-3';
                
                // Smart display name and icon
                let displayName = item.name;
                let typeIcon = item.is_folder ? '📁' : '📄';
                
                // Show original filename for DVC metadata items
                if (item.name.endsWith('.dvc') && item.source.includes('dvc')) {
                    displayName = item.name.slice(0, -4); // Remove .dvc extension
                    typeIcon = '🔧'; // Different icon for DVC items
                }
                
                // Show DVC status badge - only show if item has DVC metadata linked
                let dvcBadge = '';
                if (item.dvc_metadata_id) {
                    dvcBadge = '<span class="badge bg-success ms-2">DVC</span>';
                }
                
                let sizeInfo;
                if (item.is_folder) {
                    const sizeText = formatFileSize(item.file_size);
                    const fileCount = item.file_count || 0;
                    sizeInfo = `${sizeText} (${fileCount} files)`;
                } else {
                    sizeInfo = formatFileSize(item.file_size);
                }
                
                card.innerHTML = `
                    <div class="card">
                        <div class="card-body">
                            <h5 class="card-title">${typeIcon} ${displayName}${dvcBadge} 
                                <span class="badge ${item.is_public ? 'bg-success' : 'bg-secondary'} ms-2">
                                    ${item.is_public ? '公开' : '私有'}
                                </span>
                            </h5>
                            <p class="card-text">
                                ${item.project ? `<strong>所属项目:</strong> ${item.project}<br>` : '<strong>所属项目:</strong> 无<br>'}
                                <strong>数据来源:</strong> ${item.source}<br>
                                <strong>上传用户：</strong> ${item.user_email}<br>
                                <strong>文件类型:</strong> ${item.file_type || '未知'}<br>
                                <strong>文件大小:</strong> ${sizeInfo}<br>
                                <strong>创建时间:</strong> ${new Date(item.created_at).toLocaleDateString()}
                            </p>
                            ${item.description ? `<p class="card-text">${item.description}</p>` : ''}
                            
                            ${currentUser ? `
                            <div class="d-grid gap-2 mt-3">
                                <button class="btn btn-primary btn-sm" onclick="downloadDataFile(${item.id})">
                                    下载数据文件
                                </button>
                                <button class="btn btn-secondary btn-sm" onclick="downloadDvcFile(${item.id})">
                                    下载 DVC 文件
                                </button>
                                <button class="btn btn-info btn-sm" onclick="copyDvcString(${item.id})">
                                    拷贝 DVC 字符串
                                </button>
                                <button class="btn btn-success btn-sm" onclick="viewLineageGraph(${item.id}, '${displayName.replace(/'/g, "\\'")}')">
                                    查看数据血缘
                                </button>
                                ${item.user_id === currentUser.id ? `
                                    ${!item.is_public ? `
                                    <button class="btn btn-warning btn-sm" onclick="makePublic(${item.id})">
                                        转为公开
                                    </button>
                                    <button class="btn btn-danger btn-sm" onclick="confirmDeleteDataItem(${item.id}, '${displayName.replace(/'/g, "\\'")}')">
                                        删除
                                    </button>
                                    ` : `
                                    <button class="btn btn-secondary btn-sm" disabled title="公开数据无法删除">
                                        公开数据 (不可删除)
                                    </button>
                                    `}
                                ` : ''}
                                ${currentUser.is_admin && item.user_id !== currentUser.id ? `
                                <button class="btn btn-warning btn-sm" onclick="confirmAdminDeleteDataItem(${item.id}, '${displayName.replace(/'/g, "\\'")}', 'User ${item.user_id}')">
                                    管理员删除
                                </button>
                                ` : ''}
                            </div>
                            ` : ''}
                        </div>
                    </div>
                `;
                container.appendChild(card);
            });
            
            // Show/hide login message based on authentication state
            updateLoginMessage();
        }

        function updateLoginMessage() {
            const messageContainer = document.getElementById('loginMessageContainer');
            messageContainer.innerHTML = '';
            
            // Add login message if user is not authenticated
            if (!currentUser) {
                const messageDiv = document.createElement('div');
                messageDiv.className = 'alert alert-info text-center';
                messageDiv.innerHTML = `
                    <h5>目前处于浏览模式</h5>
                    <p class="mb-0">请 <a href="/login" class="alert-link">登录</a> 或 <a href="/register" class="alert-link">注册</a> 以上传和下载数据文件</p>
                `;
                messageContainer.appendChild(messageDiv);
            }
        }

        function updateParentOptions(dataItems) {
            const select = document.getElementById('parentItem');
            if (select) {
                select.innerHTML = '<option value="">None</option>';
                
                dataItems.forEach(item => {
                    const option = document.createElement('option');
                    option.value = item.id;
                    option.textContent = item.name;
                    select.appendChild(option);
                });
            }
        }

        let currentDownloadXhr = null;

        async function downloadDataFile(itemId) {
            try {
                // Get item info for filename
                const itemResponse = await fetch(`/api/data/${itemId}`, {
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (!itemResponse.ok) {
                    alert('获取文件信息失败: ' + (await itemResponse.text()));
                    return;
                }
                
                const item = await itemResponse.json();
                const fileName = item.name || 'data_file';
                
                // Show download progress modal
                showDownloadModal(fileName);
                
                // Use XMLHttpRequest for progress tracking
                const xhr = new XMLHttpRequest();
                currentDownloadXhr = xhr;
                
                // Track download progress
                let startTime = Date.now();
                let lastProgressTime = startTime;
                let lastLoadedBytes = 0;
                let speedSamples = [];
                
                xhr.addEventListener('progress', (e) => {
                    if (e.lengthComputable) {
                        const currentTime = Date.now();
                        const timeDiff = (currentTime - lastProgressTime) / 1000; // seconds
                        const bytesDiff = e.loaded - lastLoadedBytes;
                        
                        // Calculate current speed
                        if (timeDiff > 0) {
                            const currentSpeed = bytesDiff / timeDiff;
                            speedSamples.push(currentSpeed);
                            
                            // Keep only last 5 samples for smoothing
                            if (speedSamples.length > 5) {
                                speedSamples.shift();
                            }
                        }
                        
                        // Update progress display
                        updateDownloadProgress(e.loaded, e.total, speedSamples, currentTime - startTime);
                        
                        lastProgressTime = currentTime;
                        lastLoadedBytes = e.loaded;
                    }
                });
                
                // Handle download completion
                xhr.addEventListener('load', () => {
                    if (xhr.status === 200) {
                        // Create blob and trigger download
                        const blob = new Blob([xhr.response]);
                        const url = window.URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = xhr.getResponseHeader('Content-Disposition')?.split('filename=')[1]?.replace(/"/g, '') || fileName;
                        document.body.appendChild(a);
                        a.click();
                        window.URL.revokeObjectURL(url);
                        document.body.removeChild(a);
                        
                        // Show completion message
                        showDownloadComplete();
                    } else {
                        showDownloadError('下载失败: ' + xhr.statusText);
                    }
                    currentDownloadXhr = null;
                });
                
                // Handle errors
                xhr.addEventListener('error', () => {
                    showDownloadError('网络错误');
                    currentDownloadXhr = null;
                });
                
                xhr.addEventListener('abort', () => {
                    showDownloadCancelled();
                    currentDownloadXhr = null;
                });
                
                // Configure and send request
                xhr.open('GET', `/api/data/${itemId}/download`);
                xhr.responseType = 'blob';
                if (authToken) {
                    xhr.setRequestHeader('Authorization', `Bearer ${authToken}`);
                }
                xhr.send();
                
            } catch (error) {
                console.error('Error downloading data file:', error);
                showDownloadError('下载失败: ' + error.message);
            }
        }

        function showDownloadModal(fileName) {
            document.getElementById('downloadFileName').textContent = fileName;
            document.getElementById('downloadPercentage').textContent = '0%';
            document.getElementById('downloadProgressBar').style.width = '0%';
            document.getElementById('downloadProgressBar').textContent = '0%';
            document.getElementById('downloadedSize').textContent = '0 MB';
            document.getElementById('totalSize').textContent = '未知';
            document.getElementById('downloadSpeed').textContent = '0 MB/s';
            document.getElementById('downloadETA').textContent = '计算中...';
            
            const modal = new bootstrap.Modal(document.getElementById('downloadProgressModal'));
            modal.show();
        }

        function updateDownloadProgress(loaded, total, speedSamples, elapsedTime) {
            const percentage = Math.round((loaded / total) * 100);
            const loadedMB = (loaded / 1024 / 1024).toFixed(2);
            const totalMB = (total / 1024 / 1024).toFixed(2);
            
            // Update progress bar
            document.getElementById('downloadPercentage').textContent = percentage + '%';
            document.getElementById('downloadProgressBar').style.width = percentage + '%';
            document.getElementById('downloadProgressBar').textContent = percentage + '%';
            document.getElementById('downloadProgressBar').setAttribute('aria-valuenow', percentage);
            
            // Update sizes
            document.getElementById('downloadedSize').textContent = loadedMB + ' MB';
            document.getElementById('totalSize').textContent = totalMB + ' MB';
            
            // Calculate average speed from samples
            if (speedSamples.length > 0) {
                const avgSpeed = speedSamples.reduce((a, b) => a + b, 0) / speedSamples.length;
                const speedMBps = (avgSpeed / 1024 / 1024).toFixed(2);
                document.getElementById('downloadSpeed').textContent = speedMBps + ' MB/s';
                
                // Calculate ETA
                const remainingBytes = total - loaded;
                if (avgSpeed > 0 && remainingBytes > 0) {
                    const remainingSeconds = remainingBytes / avgSpeed;
                    const eta = formatTime(remainingSeconds);
                    document.getElementById('downloadETA').textContent = eta;
                } else if (remainingBytes <= 0) {
                    document.getElementById('downloadETA').textContent = '完成';
                }
            }
        }

        function formatTime(seconds) {
            if (seconds < 60) {
                return Math.round(seconds) + ' 秒';
            } else if (seconds < 3600) {
                const minutes = Math.floor(seconds / 60);
                const remainingSeconds = Math.round(seconds % 60);
                return `${minutes} 分 ${remainingSeconds} 秒`;
            } else {
                const hours = Math.floor(seconds / 3600);
                const minutes = Math.floor((seconds % 3600) / 60);
                return `${hours} 小时 ${minutes} 分`;
            }
        }

        function showDownloadComplete() {
            const progressBar = document.getElementById('downloadProgressBar');
            progressBar.classList.remove('progress-bar-animated');
            progressBar.classList.add('bg-success');
            document.getElementById('downloadETA').textContent = '下载完成！';
            
            setTimeout(() => {
                bootstrap.Modal.getInstance(document.getElementById('downloadProgressModal')).hide();
                progressBar.classList.remove('bg-success');
                progressBar.classList.add('progress-bar-animated');
            }, 2000);
        }

        function showDownloadError(message) {
            const progressBar = document.getElementById('downloadProgressBar');
            progressBar.classList.remove('progress-bar-animated');
            progressBar.classList.add('bg-danger');
            document.getElementById('downloadETA').textContent = message;
            
            setTimeout(() => {
                bootstrap.Modal.getInstance(document.getElementById('downloadProgressModal')).hide();
                progressBar.classList.remove('bg-danger');
                progressBar.classList.add('progress-bar-animated');
            }, 3000);
        }

        function showDownloadCancelled() {
            const progressBar = document.getElementById('downloadProgressBar');
            progressBar.classList.remove('progress-bar-animated');
            progressBar.classList.add('bg-warning');
            document.getElementById('downloadETA').textContent = '下载已取消';
            
            setTimeout(() => {
                bootstrap.Modal.getInstance(document.getElementById('downloadProgressModal')).hide();
                progressBar.classList.remove('bg-warning');
                progressBar.classList.add('progress-bar-animated');
            }, 2000);
        }

        // Cancel download handler
        document.getElementById('cancelDownloadButton').addEventListener('click', () => {
            if (currentDownloadXhr) {
                currentDownloadXhr.abort();
            }
        });

        async function downloadDvcFile(itemId) {
            try {
                const response = await fetch(`/api/data/${itemId}/dvc`, {
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    const blob = await response.blob();
                    const url = window.URL.createObjectURL(blob);
                    const a = document.createElement('a');
                    a.href = url;
                    a.download = response.headers.get('Content-Disposition')?.split('filename=')[1]?.replace(/"/g, '') || 'data_file.dvc';
                    document.body.appendChild(a);
                    a.click();
                    window.URL.revokeObjectURL(url);
                    document.body.removeChild(a);
                } else {
                    alert('下载失败: ' + (await response.text()));
                }
            } catch (error) {
                console.error('Error downloading DVC file:', error);
                alert('下载失败: ' + error.message);
            }
        }

        async function copyDvcString(itemId) {
            try {
                const response = await fetch(`/api/data/${itemId}/dvc/content`, {
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    const dvcContent = await response.text();
                    
                    // Try to copy to clipboard with fallback
                    if (navigator.clipboard && window.isSecureContext) {
                        try {
                            await navigator.clipboard.writeText(dvcContent);
                            
                            // Show success message
                            const buttons = document.querySelectorAll(`button[onclick*="copyDvcString(${itemId})"]`);
                            if (buttons.length > 0) {
                                const button = buttons[0];
                                const originalText = button.textContent;
                                button.textContent = '已拷贝!';
                                button.classList.remove('btn-info');
                                button.classList.add('btn-success');
                                
                                setTimeout(() => {
                                    button.textContent = originalText;
                                    button.classList.remove('btn-success');
                                    button.classList.add('btn-info');
                                }, 2000);
                            }
                        } catch (clipboardError) {
                            // Fallback: create temporary textarea and copy manually
                            const textArea = document.createElement('textarea');
                            textArea.value = dvcContent;
                            textArea.style.position = 'fixed';
                            textArea.style.left = '-999999px';
                            textArea.style.top = '-999999px';
                            document.body.appendChild(textArea);
                            textArea.focus();
                            textArea.select();
                            
                            try {
                                document.execCommand('copy');
                                
                                // Show success message
                                const buttons = document.querySelectorAll(`button[onclick*="copyDvcString(${itemId})"]`);
                                if (buttons.length > 0) {
                                    const button = buttons[0];
                                    const originalText = button.textContent;
                                    button.textContent = '已拷贝!';
                                    button.classList.remove('btn-info');
                                    button.classList.add('btn-success');
                                    
                                    setTimeout(() => {
                                        button.textContent = originalText;
                                        button.classList.remove('btn-success');
                                        button.classList.add('btn-info');
                                    }, 2000);
                                }
                            } catch (fallbackError) {
                                alert('拷贝失败: 请手动复制内容');
                                console.error('Fallback copy failed:', fallbackError);
                            } finally {
                                document.body.removeChild(textArea);
                            }
                        }
                    } else {
                        // Fallback for browsers without clipboard API
                        const textArea = document.createElement('textarea');
                        textArea.value = dvcContent;
                        textArea.style.position = 'fixed';
                        textArea.style.left = '-999999px';
                        textArea.style.top = '-999999px';
                        document.body.appendChild(textArea);
                        textArea.focus();
                        textArea.select();
                        
                        try {
                            document.execCommand('copy');
                            alert('DVC内容已复制到剪贴板');
                        } catch (fallbackError) {
                            alert('拷贝失败: 请手动复制内容');
                            console.error('Manual copy failed:', fallbackError);
                        } finally {
                            document.body.removeChild(textArea);
                        }
                    }
                } else {
                    alert('拷贝失败: ' + (await response.text()));
                }
            } catch (error) {
                console.error('Error copying DVC string:', error);
                alert('拷贝失败: ' + error.message);
            }
        }

        async function viewLineage(itemId) {
            try {
                const response = await fetch(`/api/data/${itemId}`, {
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    const item = await response.json();
                    displayLineage(item);
                    new bootstrap.Modal(document.getElementById('lineageModal')).show();
                }
            } catch (error) {
                console.error('Error loading lineage:', error);
            }
        }

        function displayLineage(item) {
            const container = document.getElementById('lineageContent');
            let html = `<h6>${item.name}</h6>`;
            
            if (item.parent) {
                html += `<div class="mb-3">
                    <strong>Parent:</strong> ${item.parent.name}
                </div>`;
            }
            
            if (item.children && item.children.length > 0) {
                html += `<div class="mb-3">
                    <strong>Children:</strong>
                    <ul>`;
                item.children.forEach(child => {
                    html += `<li>${child.name}</li>`;
                });
                html += `</ul></div>`;
            }
            
            if (!item.parent && (!item.children || item.children.length === 0)) {
                html += `<p>No lineage information available.</p>`;
            }
            
            container.innerHTML = html;
        }

        function updatePageTitle(userOnly) {
            const titleElement = document.getElementById('pageTitle');
            if (currentUser) {
                titleElement.textContent = userOnly ? '我的数据' : '数据仓库';
            } else {
                titleElement.textContent = '数据仓库';
            }
        }

        function formatFileSize(bytes) {
            if (!bytes) return 'Unknown';
            const sizes = ['Bytes', 'KB', 'MB', 'GB'];
            if (bytes === 0) return '0 Bytes';
            const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
            return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
        }

        function logout() {
            localStorage.removeItem('token');
            // Clear the cookie as well
            document.cookie = 'access_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Strict';
            window.location.href = '/';
        }

        // Handle upload type selection
        document.getElementById('fileUpload').addEventListener('change', function() {
            const fileInput = document.getElementById('uploadFile');
            const helpText = document.getElementById('uploadHelpText');
            fileInput.removeAttribute('webkitdirectory');
            fileInput.removeAttribute('directory');
            helpText.textContent = '支持选择多个文件，或选择文件夹上传其中所有文件。';
        });

        document.getElementById('folderUpload').addEventListener('change', function() {
            const fileInput = document.getElementById('uploadFile');
            const helpText = document.getElementById('uploadHelpText');
            fileInput.setAttribute('webkitdirectory', '');
            fileInput.setAttribute('directory', '');
            helpText.textContent = '选择文件夹上传，将上传文件夹中所有文件。';
        });

        document.getElementById('uploadForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            console.log('Upload form submitted');
            console.log('Auth token exists:', !!authToken);
            
            const files = document.getElementById('uploadFile').files;
            console.log('Files selected:', files.length);
            
            if (files.length === 0) {
                document.getElementById('uploadMessage').innerHTML = '<div class="alert alert-danger">Please select at least one file</div>';
                return;
            }
            
            // Show progress bar and hide upload button
            document.getElementById('uploadProgress').style.display = 'block';
            document.getElementById('uploadButton').disabled = true;
            document.getElementById('uploadMessage').innerHTML = '';
            
            const formData = new FormData();
            
            // Add all files to FormData
            for (let i = 0; i < files.length; i++) {
                formData.append('files', files[i]);
            }
            
            
            formData.append('project', document.getElementById('itemProject').value);
            formData.append('source', document.getElementById('itemSource').value);
            formData.append('description', document.getElementById('itemDescription').value);
            formData.append('is_public', document.getElementById('makePublic').checked);
            
            const parentId = document.getElementById('parentItem').value;
            if (parentId) {
                formData.append('parent_id', parentId);
            }
            
            const messageDiv = document.getElementById('uploadMessage');
            const progressBar = document.querySelector('.progress-bar');
            const statusText = document.getElementById('uploadStatus');
            
            // Calculate total file size for progress tracking
            let totalSize = 0;
            for (let i = 0; i < files.length; i++) {
                totalSize += files[i].size;
            }
            
            try {
                // Use XMLHttpRequest for progress tracking
                const xhr = new XMLHttpRequest();
                
                // Progress tracking
                xhr.upload.addEventListener('progress', (e) => {
                    if (e.lengthComputable) {
                        const percentComplete = (e.loaded / e.total) * 100;
                        progressBar.style.width = percentComplete + '%';
                        progressBar.setAttribute('aria-valuenow', percentComplete);
                        progressBar.textContent = Math.round(percentComplete) + '%';
                        
                        const loadedMB = (e.loaded / 1024 / 1024).toFixed(2);
                        const totalMB = (e.total / 1024 / 1024).toFixed(2);
                        statusText.textContent = `Uploading: ${loadedMB} MB / ${totalMB} MB`;
                    }
                });
                
                // Handle response
                xhr.addEventListener('load', () => {
                    if (xhr.status === 200) {
                        try {
                            const result = JSON.parse(xhr.responseText);
                            messageDiv.innerHTML = `<div class="alert alert-success">${result.message}</div>`;
                            document.getElementById('uploadForm').reset();
                            bootstrap.Modal.getInstance(document.getElementById('uploadModal')).hide();
                            loadDataItems();
                        } catch (e) {
                            messageDiv.innerHTML = '<div class="alert alert-danger">服务器响应无效</div>';
                        }
                    } else {
                        try {
                            const error = JSON.parse(xhr.responseText);
                            messageDiv.innerHTML = `<div class="alert alert-danger">${error.detail || '上传失败'}</div>`;
                        } catch (e) {
                            messageDiv.innerHTML = '<div class="alert alert-danger">上传失败</div>';
                        }
                    }
                    
                    // Hide progress bar and re-enable upload button
                    document.getElementById('uploadProgress').style.display = 'none';
                    document.getElementById('uploadButton').disabled = false;
                });
                
// Handle errors
                xhr.addEventListener('error', () => {
                    console.error('XHR error occurred');
                    console.error('XHR status:', xhr.status);
                    console.error('XHR response text:', xhr.responseText);
                    messageDiv.innerHTML = '<div class="alert alert-danger">网络错误</div>';
                    document.getElementById('uploadProgress').style.display = 'none';
                    document.getElementById('uploadButton').disabled = false;
                });
                
                xhr.addEventListener('abort', () => {
                    messageDiv.innerHTML = '<div class="alert alert-warning">上传已取消</div>';
                    document.getElementById('uploadProgress').style.display = 'none';
                    document.getElementById('uploadButton').disabled = false;
                });
                
                // Send request
                console.log('Opening XHR request to /api/data/upload');
                xhr.open('POST', '/api/data/upload');
                if (authToken) {
                    console.log('Setting Authorization header');
                    xhr.setRequestHeader('Authorization', `Bearer ${authToken}`);
                } else {
                    console.log('No auth token available');
                }
                console.log('Sending request with', formData.getAll('files').length, 'files');
                xhr.send(formData);
                
                statusText.textContent = `准备上传 ${files.length} 个文件...`;
                
            } catch (error) {
                messageDiv.innerHTML = '<div class="alert alert-danger">Network error occurred</div>';
                document.getElementById('uploadProgress').style.display = 'none';
                document.getElementById('uploadButton').disabled = false;
            }
        });

        // Initialize the page
        if (TIMING_DEBUG_ENABLED) {
            console.time('dashboard-initialization');
            console.log('TIMING: Dashboard initialization starting');
        }
        
        loadCurrentUser().then(() => {
            if (TIMING_DEBUG_ENABLED) {
                console.log('TIMING: loadCurrentUser completed, starting checkbox setup');
                console.timeEnd('dashboard-initialization');
            }
            
            // Set checkbox default state based on authentication
            const myDataCheckbox = document.getElementById('myDataCheckbox');
            if (myDataCheckbox) {
                myDataCheckbox.checked = false; // Always unchecked by default
            }
            
            if (TIMING_DEBUG_ENABLED) {
                console.log('TIMING: About to call loadDataItems');
            }
            loadDataItems();
        }).catch(error => {
            console.error('TIMING: Error in dashboard initialization:', error);
            if (TIMING_DEBUG_ENABLED) {
                console.timeEnd('dashboard-initialization');
            }
        });

        // Add event listener for checkbox only if it exists
        const myDataCheckbox = document.getElementById('myDataCheckbox');
        if (myDataCheckbox) {
            myDataCheckbox.addEventListener('change', loadDataItems);
        }
        
        // Log when page is fully loaded
        if (TIMING_DEBUG_ENABLED) {
            window.addEventListener('load', function() {
                console.timeEnd('page-load-to-script');
                console.log('TIMING: Page fully loaded');
            });
            
            // Log DOM ready state
            document.addEventListener('DOMContentLoaded', function() {
                console.log('TIMING: DOM content loaded');
            });
        }

        // Delete confirmation functions
        function confirmDeleteDataItem(itemId, itemName) {
            const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
            document.getElementById('deleteConfirmTitle').textContent = '确认删除';
            document.getElementById('deleteConfirmBody').textContent = `确定要删除数据项 "${itemName}" 吗？此操作无法撤销。`;
            
            const confirmButton = document.getElementById('confirmDeleteButton');
            confirmButton.textContent = '删除';
            confirmButton.className = 'btn btn-danger';
            confirmButton.onclick = () => deleteDataItem(itemId);
            
            modal.show();
        }

        function confirmAdminDeleteDataItem(itemId, itemName, ownerEmail) {
            const modal = new bootstrap.Modal(document.getElementById('deleteConfirmModal'));
            document.getElementById('deleteConfirmTitle').textContent = '管理员删除确认';
            document.getElementById('deleteConfirmBody').textContent = `确定要以管理员身份删除用户 "${ownerEmail}" 的数据项 "${itemName}" 吗？此操作无法撤销。`;
            
            const confirmButton = document.getElementById('confirmDeleteButton');
            confirmButton.textContent = '管理员删除';
            confirmButton.className = 'btn btn-warning';
            confirmButton.onclick = () => adminDeleteDataItem(itemId);
            
            modal.show();
        }

        async function deleteDataItem(itemId) {
            try {
                const response = await fetch(`/api/data/${itemId}`, {
                    method: 'DELETE',
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    // Handle 204 No Content response (successful deletion)
                    let result = {};
                    if (response.status !== 204) {
                        result = await response.json();
                    }
                    
                    // Show success message
                    const messageDiv = document.createElement('div');
                    messageDiv.className = 'alert alert-success alert-dismissible fade show position-fixed';
                    messageDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
                    messageDiv.innerHTML = `
                        ${result.message || '文件删除成功'}
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    `;
                    document.body.appendChild(messageDiv);
                    
                    // Hide modal and reload data
                    bootstrap.Modal.getInstance(document.getElementById('deleteConfirmModal')).hide();
                    loadDataItems();
                    
                    // Auto-remove message after 5 seconds
                    setTimeout(() => {
                        if (messageDiv.parentNode) {
                            messageDiv.parentNode.removeChild(messageDiv);
                        }
                    }, 5000);
                } else {
                    const error = await response.json();
                    alert('删除失败: ' + (error.detail || '未知错误'));
                }
            } catch (error) {
                console.error('Error deleting data item:', error);
                alert('删除失败: ' + error.message);
            }
        }

        async function adminDeleteDataItem(itemId) {
            try {
                const response = await fetch(`/api/admin/data/${itemId}`, {
                    method: 'DELETE',
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    // Handle 204 No Content response (successful deletion)
                    let result = {};
                    if (response.status !== 204) {
                        result = await response.json();
                    }
                    
                    // Show success message
                    const messageDiv = document.createElement('div');
                    messageDiv.className = 'alert alert-success alert-dismissible fade show position-fixed';
                    messageDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
                    messageDiv.innerHTML = `
                        ${result.message || '文件删除成功'}
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    `;
                    document.body.appendChild(messageDiv);
                    
                    // Hide modal and reload data
                    bootstrap.Modal.getInstance(document.getElementById('deleteConfirmModal')).hide();
                    loadDataItems();
                    
                    // Auto-remove message after 5 seconds
                    setTimeout(() => {
                        if (messageDiv.parentNode) {
                            messageDiv.parentNode.removeChild(messageDiv);
                        }
                    }, 5000);
                } else {
                    const error = await response.json();
                    alert('删除失败: ' + (error.detail || '未知错误'));
                }
            } catch (error) {
                console.error('Error deleting data item:', error);
                alert('删除失败: ' + error.message);
            }
        }

        async function makePublic(itemId) {
            if (!confirm('确定要将此数据设为公开吗？公开后将无法删除。')) {
                return;
            }
            
            try {
                const response = await fetch(`/api/data/${itemId}/public`, {
                    method: 'PUT',
                    headers: authToken ? {
                        'Authorization': `Bearer ${authToken}`
                    } : {}
                });
                
                if (response.ok) {
                    // Show success message
                    const messageDiv = document.createElement('div');
                    messageDiv.className = 'alert alert-success alert-dismissible fade show position-fixed';
                    messageDiv.style.cssText = 'top: 20px; right: 20px; z-index: 9999; min-width: 300px;';
                    messageDiv.innerHTML = `
                        数据已设为公开
                        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
                    `;
                    document.body.appendChild(messageDiv);
                    
                    // Reload data to show updated status
                    loadDataItems();
                    
                    // Auto-remove message after 3 seconds
                    setTimeout(() => {
                        if (messageDiv.parentNode) {
                            messageDiv.parentNode.removeChild(messageDiv);
                        }
                    }, 3000);
                } else {
                    const error = await response.json();
                    alert('设为公开失败: ' + (error.detail || '未知错误'));
                }
            } catch (error) {
                console.error('Error making data public:', error);
                alert('设为公开失败: ' + error.message);
            }
        }

        // Helper function for authenticated fetch requests
        async function authenticatedFetch(url, options = {}) {
            const headers = {
                ...options.headers,
                ...(authToken ? { 'Authorization': `Bearer ${authToken}` } : {})
            };
            
            return fetch(url, {
                ...options,
                headers
            });
        }

        // Lineage Management Functions
        async function viewLineageGraph(itemId, itemName) {
            try {
                // Store current item ID for other functions
                currentLineageItemId = itemId;
                
                // Show loading modal
                showLineageModal(itemName);

                // Load lineage graph data
                const graphResponse = await authenticatedFetch(`/api/lineage/graph?center_item_id=${itemId}&max_depth=3`);
                if (!graphResponse.ok) {
                    throw new Error('Failed to load lineage graph');
                }

                const graphData = await graphResponse.json();

                // Load lineage statistics
                const statsResponse = await authenticatedFetch('/api/lineage/stats');
                const statsData = statsResponse.ok ? await statsResponse.json() : null;

                // Display the graph
                displayLineageGraph(graphData, statsData);

                // Load lineage suggestions
                loadLineageSuggestions(itemId);

            } catch (error) {
                console.error('Error loading lineage graph:', error);
                alert('加载血缘图失败: ' + error.message);
            }
        }

        function showLineageModal(itemName) {
            const modalHtml = `
                <div class="modal fade" id="lineageModal" tabindex="-1">
                    <div class="modal-dialog modal-xl">
                        <div class="modal-content">
                            <div class="modal-header">
                                <h5 class="modal-title">数据血缘图谱 - ${itemName}</h5>
                                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                            </div>
                            <div class="modal-body">
                                <div class="row">
                                    <div class="col-md-8">
                                        <div class="card">
                                            <div class="card-header">
                                                <h6>血缘关系图</h6>
                                            </div>
                                            <div class="card-body">
                                                <div id="lineageGraphContainer" style="height: 500px; border: 1px solid #ddd; position: relative;">
                                                    <div class="d-flex justify-content-center align-items-center h-100">
                                                        <div class="text-center">
                                                            <div class="spinner-border text-primary" role="status">
                                                                <span class="visually-hidden">Loading...</span>
                                                            </div>
                                                            <div class="mt-2">正在加载血缘数据...</div>
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="col-md-4">
                                        <div class="card mb-3">
                                            <div class="card-header">
                                                <h6>血缘统计</h6>
                                            </div>
                                            <div class="card-body" id="lineageStats">
                                                <div class="text-center">
                                                    <div class="spinner-border spinner-border-sm text-primary" role="status">
                                                        <span class="visually-hidden">Loading...</span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>

                                        <div class="card">
                                            <div class="card-header">
                                                <h6>血缘建议</h6>
                                                <button class="btn btn-sm btn-outline-primary" onclick="detectLineageForCurrentItem()">
                                                    <i class="bi bi-search"></i> 智能检测
                                                </button>
                                            </div>
                                            <div class="card-body" id="lineageSuggestions">
                                                <div class="text-center">
                                                    <div class="spinner-border spinner-border-sm text-primary" role="status">
                                                        <span class="visually-hidden">Loading...</span>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer">
                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                                <button type="button" class="btn btn-primary" onclick="exportLineageGraph()">导出图谱</button>
                            </div>
                        </div>
                    </div>
                </div>
            `;

            // Remove existing modal if present
            const existingModal = document.getElementById('lineageModal');
            if (existingModal) {
                existingModal.remove();
            }

            // Add modal to body and show
            document.body.insertAdjacentHTML('beforeend', modalHtml);
            const modal = new bootstrap.Modal(document.getElementById('lineageModal'));
            modal.show();
        }

        function displayLineageGraph(graphData, statsData) {
            const container = document.getElementById('lineageGraphContainer');

            if (graphData.nodes.length === 0) {
                container.innerHTML = `
                    <div class="d-flex justify-content-center align-items-center h-100">
                        <div class="text-center text-muted">
                            <i class="bi bi-diagram-3" style="font-size: 3rem;"></i>
                            <div class="mt-2">暂无血缘关系</div>
                            <button class="btn btn-sm btn-outline-primary mt-2" onclick="detectLineageForCurrentItem()">
                                智能检测血缘关系
                            </button>
                        </div>
                    </div>
                `;
                return;
            }

            // Simple SVG visualization (you could use D3.js or Vis.js for more complex graphs)
            let svgContent = '<svg width="100%" height="100%" viewBox="0 0 800 500">';

            // Create nodes
            graphData.nodes.forEach((node, index) => {
                const x = 100 + (index % 4) * 180;
                const y = 50 + Math.floor(index / 4) * 120;
                const color = node.node_type === 'center' ? '#0d6efd' :
                            node.node_type === 'source' ? '#198754' : '#6c757d';

                svgContent += `
                    <circle cx="${x}" cy="${y}" r="30" fill="${color}" stroke="#fff" stroke-width="2"/>
                    <text x="${x}" y="${y + 5}" text-anchor="middle" fill="white" font-size="12" font-weight="bold">
                        ${node.name.length > 15 ? node.name.substring(0, 12) + '...' : node.name}
                    </text>
                    <text x="${x}" y="${y + 45}" text-anchor="middle" fill="#666" font-size="10">
                        ${node.user_email}
                    </text>
                `;
            });

            // Create edges
            graphData.edges.forEach((edge, index) => {
                const fromNode = graphData.nodes.find(n => n.id === edge.from);
                const toNode = graphData.nodes.find(n => n.id === edge.to);

                if (fromNode && toNode) {
                    const fromIndex = graphData.nodes.indexOf(fromNode);
                    const toIndex = graphData.nodes.indexOf(toNode);

                    const fromX = 100 + (fromIndex % 4) * 180;
                    const fromY = 50 + Math.floor(fromIndex / 4) * 120;
                    const toX = 100 + (toIndex % 4) * 180;
                    const toY = 50 + Math.floor(toIndex / 4) * 120;

                    svgContent += `
                        <line x1="${fromX}" y1="${fromY}" x2="${toX}" y2="${toY}"
                              stroke="#666" stroke-width="2" marker-end="url(#arrowhead)"/>
                    `;
                }
            });

            // Add arrowhead marker
            svgContent += `
                <defs>
                    <marker id="arrowhead" markerWidth="10" markerHeight="10"
                            refX="9" refY="3" orient="auto">
                        <polygon points="0 0, 10 3, 0 6" fill="#666"/>
                    </marker>
                </defs>
            `;

            svgContent += '</svg>';

            container.innerHTML = svgContent;

            // Display statistics
            if (statsData) {
                displayLineageStats(statsData);
            }
        }

        function displayLineageStats(stats) {
            const statsContainer = document.getElementById('lineageStats');

            statsContainer.innerHTML = `
                <div class="row text-center">
                    <div class="col-6">
                        <div class="fs-4 fw-bold text-primary">${stats.total_relationships}</div>
                        <div class="small text-muted">总关系数</div>
                    </div>
                    <div class="col-6">
                        <div class="fs-4 fw-bold text-success">${stats.auto_detected_relationships}</div>
                        <div class="small text-muted">自动检测</div>
                    </div>
                </div>
                <hr>
                <div class="mb-2">
                    <small class="text-muted">关系类型分布:</small>
                </div>
                ${stats.relationships_by_type.map(([type, count]) => `
                    <div class="d-flex justify-content-between align-items-center mb-1">
                        <span class="badge bg-secondary">${type}</span>
                        <span class="badge bg-primary">${count}</span>
                    </div>
                `).join('')}
                <hr>
                <div class="mb-2">
                    <small class="text-muted">检测方式分布:</small>
                </div>
                ${stats.relationships_by_method.map(([method, count]) => `
                    <div class="d-flex justify-content-between align-items-center mb-1">
                        <span class="badge bg-info">${method}</span>
                        <span class="badge bg-primary">${count}</span>
                    </div>
                `).join('')}
                <hr>
                <div class="text-center">
                    <small class="text-muted">平均置信度: ${(stats.average_confidence * 100).toFixed(1)}%</small>
                </div>
            `;
        }

        async function loadLineageSuggestions(itemId) {
            try {
                const response = await authenticatedFetch(`/api/lineage/suggestions?child_id=${itemId}&status=pending&limit=5`);
                if (!response.ok) {
                    throw new Error('Failed to load lineage suggestions');
                }

                const suggestions = await response.json();
                displayLineageSuggestions(suggestions);

            } catch (error) {
                console.error('Error loading lineage suggestions:', error);
                document.getElementById('lineageSuggestions').innerHTML = `
                    <div class="text-center text-muted">
                        <small>加载建议失败</small>
                    </div>
                `;
            }
        }

        function displayLineageSuggestions(suggestions) {
            const container = document.getElementById('lineageSuggestions');

            if (suggestions.length === 0) {
                container.innerHTML = `
                    <div class="text-center text-muted">
                        <small>暂无血缘建议</small>
                        <button class="btn btn-sm btn-outline-primary mt-2 d-block" onclick="detectLineageForCurrentItem()">
                            智能检测血缘关系
                        </button>
                    </div>
                `;
                return;
            }

            container.innerHTML = suggestions.map(suggestion => `
                <div class="card mb-2 border-warning">
                    <div class="card-body p-2">
                        <div class="d-flex justify-content-between align-items-start">
                            <div>
                                <small class="text-muted">建议关系:</small><br>
                                <strong>${suggestion.parent_item.name}</strong><br>
                                <i class="bi bi-arrow-down text-success"></i><br>
                                <strong>${suggestion.child_item.name}</strong>
                            </div>
                            <div class="text-end">
                                <span class="badge bg-warning">${(suggestion.suggestion.confidence_score * 100).toFixed(0)}%</span>
                            </div>
                        </div>
                        <div class="mt-2">
                            <small class="text-muted">${suggestion.suggestion.suggestion_reason}</small>
                        </div>
                        <div class="mt-2 btn-group btn-group-sm">
                            <button class="btn btn-success" onclick="processLineageSuggestion(${suggestion.suggestion.id}, 'accept')">
                                接受
                            </button>
                            <button class="btn btn-outline-secondary" onclick="processLineageSuggestion(${suggestion.suggestion.id}, 'reject')">
                                拒绝
                            </button>
                        </div>
                    </div>
                </div>
            `).join('');
        }

        async function processLineageSuggestion(suggestionId, action) {
            try {
                const response = await authenticatedFetch('/api/lineage/suggestions/process', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        suggestion_id: suggestionId,
                        action: action
                    })
                });

                if (!response.ok) {
                    throw new Error('Failed to process suggestion');
                }

                // Reload suggestions
                const modal = bootstrap.Modal.getInstance(document.getElementById('lineageModal'));
                if (modal) {
                    // Get the current item ID from the modal (you might want to store this)
                    const currentItemId = getCurrentItemId(); // You'd need to implement this
                    if (currentItemId) {
                        loadLineageSuggestions(currentItemId);
                    }
                }

                // Show success message
                const actionText = action === 'accept' ? '已接受' : '已拒绝';
                showNotification(`血缘建议${actionText}`, 'success');

            } catch (error) {
                console.error('Error processing lineage suggestion:', error);
                showNotification('处理建议失败: ' + error.message, 'danger');
            }
        }

        async function detectLineageForCurrentItem() {
            // You'd need to implement getCurrentItemId() to get the current item ID
            const currentItemId = getCurrentItemId();
            if (!currentItemId) {
                showNotification('无法确定当前数据项', 'warning');
                return;
            }

            try {
                const response = await authenticatedFetch(`/api/lineage/detect/${currentItemId}`, {
                    method: 'POST'
                });

                if (!response.ok) {
                    throw new Error('Failed to detect lineage');
                }

                const suggestions = await response.json();
                showNotification(`智能检测到 ${suggestions.length} 个血缘建议`, 'success');

                // Reload suggestions display
                displayLineageSuggestions(suggestions);

            } catch (error) {
                console.error('Error detecting lineage:', error);
                showNotification('智能检测失败: ' + error.message, 'danger');
            }
        }

        function getCurrentItemId() {
            return currentLineageItemId;
        }

        function showNotification(message, type = 'info') {
            const notification = document.createElement('div');
            notification.className = `alert alert-${type} alert-dismissible fade show position-fixed top-0 end-0 m-3`;
            notification.style.zIndex = '9999';
            notification.innerHTML = `
                ${message}
                <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
            `;
            document.body.appendChild(notification);

            // Auto-remove after 3 seconds
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.parentNode.removeChild(notification);
                }
            }, 3000);
        }

        function exportLineageGraph() {
            // Placeholder for exporting functionality
            showNotification('导出功能开发中...', 'info');
        }
    </script>
</body>
</html>
